#include <functional>
#include "Log.hxx"
#include "LockGuard.hpp"
#include <pthread.h>
#include <iostream>
#include <fstream> 
#include <sstream> 
#include <map>  
#include <string>  
#include "thread.hpp"
#include "Task.hxx"
#include "Log.hxx"
class ThreadData{
    public:
    
};

  
std::map<std::string, std::string> parseConfigFile(const std::string& filePath) {  
    std::map<std::string, std::string> configMap;  
    std::ifstream configFile(filePath);  
    if (!configFile.is_open()) {  
        std::cerr << "无法打开配置文件: " << filePath << std::endl;  
        return configMap;  
    }  
  
    std::string line;  
    while (std::getline(configFile, line)) {  
        // 去除行尾的注释（如果有的话）  
        size_t commentPos = line.find('#');  
        if (commentPos != std::string::npos) {  
            line = line.substr(0, commentPos);  
        }  
  
        // 忽略空行  
        if (line.empty()) continue;  
  
        // 找到'='的位置  
        size_t pos = line.find('=');  
        if (pos == std::string::npos) {  
            // 如果没有找到'='，则忽略该行  
            continue;  
        }  
  
        // 提取键和值，并去除前后的空格  
        std::string key = line.substr(0, pos);  
        std::string value = line.substr(pos + 1);  
        key.erase(0, key.find_first_not_of(" \t"));  
        key.erase(key.find_last_not_of(" \t") + 1); 
        value.erase(0, value.find_first_not_of(" \t"));  
        value.erase(value.find_last_not_of(" \t\r\n") + 1);  
  
        // 将键值对添加到map中  
        configMap[key] = value;  
    }  
  
    configFile.close();  
    return configMap;  
}  

template <class T>
class ThreadPool{
    std::queue<T> _q;
    std::list<fuh::thread<ThreadData>> _threads;
    int _thread_num;
    int _task_num;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
    Log _lg;


    ThreadPool(int thread_num = 2)
    :_thread_num(thread_num)
    {
        std::map<std::string, std::string> conf  = parseConfigFile("ThreadPool.conf");
        _thread_num_low_water = std::stoi(conf["_thread_num_low_water"]);
        _thread_num_high_water = std::stoi(conf["_thread_num_high_water"]);
        _task_num_low_water = std::stoi(conf["_task_num_low_water"]);
        _task_num_high_water = std::stoi(conf["_task_num_high_water"]);
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);

        ThreadData td;
        AddThread(td,thread_num);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    
    
    void AddThread(ThreadData & dt,int thread_num = 2)
    {
        //实现一个每次添加和总数上限
        //...

        for(int i = 0;i<thread_num;i++)
        {
            // fuh::thread<ThreadData> t( std::bind(&ThreadPool<T>::ThreadRun,this,std::placeholders::_1),dt);
            _threads.emplace_back(fuh::thread<ThreadData> ( std::bind(&ThreadPool<T>::ThreadRun,this,std::placeholders::_1),dt));
        }
    }

    
        void THreadWait()
    {
        _lg(Log::MsgLevel::Debug,">>: Thread Is Waiting");
        pthread_cond_wait(&_cond,&_mutex);
    }
    void THreadWakeup()
    {
        pthread_cond_signal(&_cond);
        _lg(Log::MsgLevel::Debug,">>: Waken up Thread");
    }
    void ThreadRun(ThreadData & tdata)
    {
        while(1) 
        {
            T t;
            {
                LockGuard l_lock(_mutex);
                while(_q.empty())
                {
                    THreadWait();
                }
                t = _q.front();
                _q.pop();
            }
            t();
        }
    }
public:

    bool Start()
    {
        for(auto& td:_threads)
        {
            td.Start(); 
        }
        return 1;
    }
    //浮动线程池的支持,读取配置文件
    void CheckSelf()
    {
        //判断线程数量和任务数量之间的关系
        //如此来调整任务与线程的上限个数
        //可以在浮动值之间调整平衡，不局限于++，--
        //考虑线程池一般由主线程放入，其他线程执行，没开放控制任务数量的接口

        if(_task_num<_task_num_low_water)
        {
            //直接纯粹的增加任务即可,或者减少线程上线
            _task_num ++;
            if(_thread_num>1)
                _thread_num --;
        }
        if(_thread_num < _thread_num_low_water)
        {
            //纯粹的增加线程
            _thread_num++;
        }
        if(_thread_num<_thread_num_high_water && _task_num>_task_num_high_water)
        {
            //增加线程
            _thread_num++;
        }
        if(_thread_num>_thread_num_high_water &&  _task_num<_task_num_low_water) 
        {
            //增加任务
            _task_num ++;
        }
    }
    void Push(T& in)
    {
        LockGuard lock(_mutex);
        _q.push(in);
        THreadWakeup();
    }

    //把所有线程detach
    void Detach()
    {
        for(auto& td:_threads)
        {
            td.Detach();
        }
    }
    bool join()
    {
        for(auto& td:_threads)
        {
            td.join();
        }
        return 1;
    }
    

    static ThreadPool<T>* GetInstance()
    {
        if(instance_Ptr == nullptr)
        {
            LockGuard lock(&instance_mutex);
            //为什么要加两次判断，原因就是多线程访问同时进来，同时进入第一个判断是可能的，
            //但是加了锁之和就只能有一个线程进入第二个进程
            //遮掩即使一开始多个线程进入，也不会出现访问问题
            if(instance_Ptr == nullptr)
            {
                std::cout<<"创建单例成功\n";
                instance_Ptr = new ThreadPool<T>();
            }

        }
        return instance_Ptr;
    }

    static void DelInstance()
    {
        delete instance_Ptr;
        instance_Ptr = nullptr;
    }
private:
    //单例指针
    static ThreadPool<T> *instance_Ptr;
    static pthread_mutex_t instance_mutex;

    ThreadPool(const   ThreadPool<T>&) = delete;
    const ThreadPool<T> operator=(const ThreadPool<T>&) = delete;
//扩展：

    int _thread_num_low_water;
    int _thread_num_high_water;
    int _task_num_low_water;
    int _task_num_high_water;

};

template <class T>
pthread_mutex_t ThreadPool<T>:: instance_mutex = PTHREAD_MUTEX_INITIALIZER;

template <class T>
ThreadPool<T>* ThreadPool<T>::  instance_Ptr = nullptr;